home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 11 / Info-Mac_XI_Disc_1.cdr_ / Info-Mac XI Disc 1.cdr / Programs / Science & Math / MacEspresso 1.0 / espresso / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-10  |  19.0 KB  |  745 lines  |  [TEXT/R*ch]

  1. /*
  2.  * Revision Control Information
  3.  *
  4.  * $Source$
  5.  * $Author$
  6.  * $Revision$
  7.  * $Date$
  8.  *
  9.  */
  10. /*
  11.  *  Main driver for espresso
  12.  *
  13.  *  Old style -do xxx, -out xxx, etc. are still supported.
  14.  */
  15.  
  16. #include "espresso.h"
  17. #include "main.h"        /* table definitions for options */
  18. #include <console.h>
  19.  
  20. static FILE *last_fp;
  21. static int input_type = FD_type;
  22.  
  23.  
  24. main(int argc, char *argv[])
  25. {
  26.     
  27.  
  28.     int i, j, first, last, strategy, out_type, option;
  29.     pPLA PLA, PLA1;
  30.     pcover F, Fold, Dold;
  31.     pset last1, p;
  32.     cost_t cost;
  33.     bool error, exact_cover;
  34.     long start;
  35.     extern char *optarg;
  36.     extern int optind;
  37.     argc = ccommand(&argv);
  38.     start = ptime();
  39.  
  40.     error = FALSE;
  41.     init_runtime();
  42. #ifdef RANDOM
  43.     srandom(314973);
  44. #endif
  45.  
  46.     option = 0;            /* default -D: ESPRESSO */
  47.     out_type = F_type;        /* default -o: default is ON-set only */
  48.     debug = 0;            /* default -d: no debugging info */
  49.     verbose_debug = FALSE;    /* default -v: not verbose */
  50.     print_solution = TRUE;    /* default -x: print the solution (!) */
  51.     summary = FALSE;        /* default -s: no summary */
  52.     trace = FALSE;        /* default -t: no trace information */
  53.     strategy = 0;        /* default -S: strategy number */
  54.     first = -1;            /* default -R: select range */
  55.     last = -1;
  56.     remove_essential = TRUE;    /* default -e: */
  57.     force_irredundant = TRUE;
  58.     unwrap_onset = TRUE;
  59.     single_expand = FALSE;
  60.     pos = FALSE;
  61.     recompute_onset = FALSE;
  62.     use_super_gasp = FALSE;
  63.     use_random_order = FALSE;
  64.     kiss = FALSE;
  65.     echo_comments = TRUE;
  66.     echo_unknown_commands = TRUE;
  67.     exact_cover = FALSE;    /* for -qm option, the default */
  68.  
  69.     backward_compatibility_hack(&argc, argv, &option, &out_type);
  70.  
  71.  
  72.     /* parse command line options*/
  73.     while ((i = getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
  74.     switch(i) {
  75.         case 'D':        /* -Dcommand invokes a subcommand */
  76.         for(j = 0; option_table[j].name != 0; j++) {
  77.             if (strcmp(optarg, option_table[j].name) == 0) {
  78.             option = j;
  79.             break;
  80.             }
  81.         }
  82.         if (option_table[j].name == 0) {
  83.             fprintf(stderr, "%s: bad subcommand \"%s\"\n",
  84.             argv[0], optarg);
  85.             exit(1);
  86.         }
  87.         break;
  88.  
  89.         case 'o':        /* -ooutput selects and output option */
  90.         for(j = 0; pla_types[j].key != 0; j++) {
  91.             if (strcmp(optarg, pla_types[j].key+1) == 0) {
  92.             out_type = pla_types[j].value;
  93.             break;
  94.             }
  95.         }
  96.         if (pla_types[j].key == 0) {
  97.             fprintf(stderr, "%s: bad output type \"%s\"\n",
  98.             argv[0], optarg);
  99.             exit(1);
  100.         }
  101.         break;
  102.  
  103.         case 'e':        /* -eespresso selects an option for espresso */
  104.         for(j = 0; esp_opt_table[j].name != 0; j++) {
  105.             if (strcmp(optarg, esp_opt_table[j].name) == 0) {
  106.             *(esp_opt_table[j].variable) = esp_opt_table[j].value;
  107.             break;
  108.             }
  109.         }
  110.         if (esp_opt_table[j].name == 0) {
  111.             fprintf(stderr, "%s: bad espresso option \"%s\"\n",
  112.             argv[0], optarg);
  113.             exit(1);
  114.         }
  115.         break;
  116.  
  117.         case 'd':        /* -d turns on (softly) all debug switches */
  118.         debug = debug_table[0].value;
  119.         trace = TRUE;
  120.         summary = TRUE;
  121.         break;
  122.  
  123.         case 'v':        /* -vdebug invokes a debug option */
  124.         verbose_debug = TRUE;
  125.         for(j = 0; debug_table[j].name != 0; j++) {
  126.             if (strcmp(optarg, debug_table[j].name) == 0) {
  127.             debug |= debug_table[j].value;
  128.             break;
  129.             }
  130.         }
  131.         if (debug_table[j].name == 0) {
  132.             fprintf(stderr, "%s: bad debug type \"%s\"\n",
  133.             argv[0], optarg);
  134.             exit(1);
  135.         }
  136.         break;
  137.  
  138.         case 't':
  139.         trace = TRUE;
  140.         break;
  141.  
  142.         case 's':
  143.         summary = TRUE;
  144.         break;
  145.  
  146.         case 'x':        /* -x suppress printing of results */
  147.         print_solution = FALSE;
  148.         break;
  149.  
  150.         case 'S':        /* -S sets a strategy for several cmds */
  151.         strategy = atoi(optarg);
  152.         break;
  153.  
  154.         case 'r':        /* -r selects range (outputs or vars) */
  155.         if (sscanf(optarg, "%d-%d", &first, &last) < 2) {
  156.             fprintf(stderr, "%s: bad output range \"%s\"\n",
  157.             argv[0], optarg);
  158.             exit(1);
  159.         }
  160.         break;
  161.  
  162.         default:
  163.         usage();
  164.         exit(1);
  165.     }
  166.     }
  167.  
  168.     /* provide version information and summaries */
  169.     if (summary || trace) {
  170.     /* echo command line and arguments */
  171.     printf("#");
  172.     for(i = 0; i < argc; i++) {
  173.         printf(" %s", argv[i]);
  174.     }
  175.     printf("\n");
  176.     printf("# %s\n", VERSION);
  177.     }
  178.  
  179.     /* the remaining arguments are argv[optind ... argc-1] */
  180.     PLA = PLA1 = NIL(PLA_t);
  181.     switch(option_table[option].num_plas) {
  182.     case 2:
  183.         if (optind+2 < argc) fatal("trailing arguments on command line");
  184.         getPLA(optind++, argc, argv, option, &PLA, out_type);
  185.         getPLA(optind++, argc, argv, option, &PLA1, out_type);
  186.         break;
  187.     case 1:
  188.         if (optind+1 < argc) fatal("trailing arguments on command line");
  189.         getPLA(optind++, argc, argv, option, &PLA, out_type);
  190.         break;
  191.     }
  192.     if (optind < argc) fatal("trailing arguments on command line");
  193.  
  194.     if (summary || trace) {
  195.     if (PLA != NIL(PLA_t)) PLA_summary(PLA);
  196.     if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
  197.     }
  198.  
  199. /*
  200.  *  Now a case-statement to decide what to do
  201.  */
  202.  
  203.     switch(option_table[option].key) {
  204.  
  205.  
  206. /******************** Espresso operations ********************/
  207.  
  208.     case KEY_ESPRESSO:
  209.     Fold = sf_save(PLA->F);
  210.     PLA->F = espresso(PLA->F, PLA->D, PLA->R);
  211.     EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
  212.     if (error) {
  213.         print_solution = FALSE;
  214.         PLA->F = Fold;
  215.         (void) check_consistency(PLA);
  216.     } else {
  217.         free_cover(Fold);
  218.     }
  219.     break;
  220.  
  221.     case KEY_MANY_ESPRESSO: {
  222.     int pla_type;
  223.     do {
  224.         EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO   ",PLA->F);
  225.         if (print_solution) {
  226.         fprint_pla(stdout, PLA, out_type);
  227.         (void) fflush(stdout);
  228.         }
  229.         pla_type = PLA->pla_type;
  230.         free_PLA(PLA);
  231.         setdown_cube();
  232.         FREE(cube.part_size);
  233.     } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
  234.     exit(0);
  235.     }
  236.  
  237.     case KEY_simplify:
  238.     EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY  ", PLA->F);
  239.     break;
  240.  
  241.     case KEY_so:            /* minimize all functions as single-output */
  242.     if (strategy < 0 || strategy > 1) {
  243.         strategy = 0;
  244.     }
  245.     so_espresso(PLA, strategy);
  246.     break;
  247.  
  248.     case KEY_so_both:        /* minimize all functions as single-output */
  249.     if (strategy < 0 || strategy > 1) {
  250.         strategy = 0;
  251.     }
  252.     so_both_espresso(PLA, strategy);
  253.     break;
  254.  
  255.     case KEY_expand:            /* execute expand */
  256.     EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
  257.     break;
  258.  
  259.     case KEY_irred:             /* extract minimal irredundant subset */
  260.     EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
  261.     break;
  262.  
  263.     case KEY_reduce:            /* perform reduction */
  264.     EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
  265.     break;
  266.  
  267.     case KEY_essen:             /* check for essential primes */
  268.     foreach_set(PLA->F, last1, p) {
  269.         SET(p, RELESSEN);
  270.         RESET(p, NONESSEN);
  271.     }
  272.     EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
  273.     free_cover(F);
  274.     break;
  275.  
  276.     case KEY_super_gasp:
  277.     PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
  278.     break;
  279.  
  280.     case KEY_gasp:
  281.     PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
  282.     break;
  283.  
  284.     case KEY_make_sparse:       /* make_sparse step of Espresso */
  285.     PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
  286.     break;
  287.  
  288.     case KEY_exact:
  289.     exact_cover = TRUE;
  290.  
  291.     case KEY_qm:
  292.     Fold = sf_save(PLA->F);
  293.     PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
  294.     EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
  295.     if (error) {
  296.         print_solution = FALSE;
  297.         PLA->F = Fold;
  298.         (void) check_consistency(PLA);
  299.     }
  300.     free_cover(Fold);
  301.     break;
  302.  
  303.     case KEY_primes:            /* generate all prime implicants */
  304.     EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), 
  305.                             "PRIMES     ", PLA->F);
  306.     break;
  307.  
  308.     case KEY_map:               /* print out a Karnaugh map of function */
  309.     map(PLA->F);
  310.     print_solution = FALSE;
  311.     break;
  312.  
  313.     case KEY_signature:
  314.     Fold = sf_save(PLA->F);
  315.     PLA->F = signature(PLA->F, PLA->D, PLA->R);
  316.     EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
  317.     if (error) {
  318.         print_solution = FALSE;
  319.         PLA->F = Fold;
  320.         (void) check_consistency(PLA);
  321.     } else {
  322.         free_cover(Fold);
  323.     }
  324.     break;
  325.  
  326. /******************** Output phase and bit pairing ********************/
  327.  
  328.     case KEY_opo:               /* sasao output phase assignment */
  329.     phase_assignment(PLA, strategy);
  330.     break;
  331.  
  332.     case KEY_opoall:        /* try all phase assignments (!) */
  333.     if (first < 0 || first >= cube.part_size[cube.output]) {
  334.         first = 0;
  335.     }
  336.     if (last < 0 || last >= cube.part_size[cube.output]) {
  337.         last = cube.part_size[cube.output] - 1;
  338.     }
  339.     opoall(PLA, first, last, strategy);
  340.     break;
  341.  
  342.     case KEY_pair:              /* find an optimal pairing */
  343.     find_optimal_pairing(PLA, strategy);
  344.     break;
  345.  
  346.     case KEY_pairall:        /* try all pairings !! */
  347.     pair_all(PLA, strategy);
  348.     break;
  349.  
  350.  
  351.  
  352. /******************** Simple cover operations ********************/
  353.  
  354.     case KEY_echo:                /* echo the PLA */
  355.     break;
  356.  
  357.     case KEY_taut:                /* tautology check */
  358.     printf("ON-set is%sa tautology\n",
  359.         tautology(cube1list(PLA->F)) ? " " : " not ");
  360.     print_solution = FALSE;
  361.     break;
  362.  
  363.     case KEY_contain:                /* single cube containment */
  364.     PLA->F = sf_contain(PLA->F);
  365.     break;
  366.  
  367.     case KEY_intersect:                /* cover intersection */
  368.     PLA->F = cv_intersect(PLA->F, PLA1->F);
  369.     break;
  370.  
  371.     case KEY_union:                /* cover union */
  372.     PLA->F = sf_union(PLA->F, PLA1->F);
  373.     break;
  374.  
  375.     case KEY_disjoint:                /* make cover disjoint */
  376.     PLA->F = make_disjoint(PLA->F);
  377.     break;
  378.  
  379.     case KEY_dsharp:                /* cover disjoint-sharp */
  380.     PLA->F = cv_dsharp(PLA->F, PLA1->F);
  381.     break;
  382.  
  383.     case KEY_sharp:                /* cover sharp */
  384.     PLA->F = cv_sharp(PLA->F, PLA1->F);
  385.     break;
  386.  
  387.     case KEY_lexsort:                /* lexical sort order */
  388.     PLA->F = lex_sort(PLA->F);
  389.     break;
  390.  
  391.     case KEY_stats:                /* print info on size */
  392.     if (! summary) PLA_summary(PLA);
  393.     print_solution = FALSE;
  394.     break;
  395.  
  396.     case KEY_minterms:                /* explode into minterms */
  397.     if (first < 0 || first >= cube.num_vars) {
  398.         first = 0;
  399.     }
  400.     if (last < 0 || last >= cube.num_vars) {
  401.         last = cube.num_vars - 1;
  402.     }
  403.     PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
  404.     break;
  405.  
  406.     case KEY_d1merge:                /* distance-1 merge */
  407.     if (first < 0 || first >= cube.num_vars) {
  408.         first = 0;
  409.     }
  410.     if (last < 0 || last >= cube.num_vars) {
  411.         last = cube.num_vars - 1;
  412.     }
  413.     for(i = first; i <= last; i++) {
  414.         PLA->F = d1merge(PLA->F, i);
  415.     }
  416.     break;
  417.  
  418.     case KEY_d1merge_in:        /* distance-1 merge inputs only */
  419.     for(i = 0; i < cube.num_binary_vars; i++) {
  420.         PLA->F = d1merge(PLA->F, i);
  421.     }
  422.     break;
  423.  
  424.     case KEY_PLA_verify:        /* check two PLAs for equivalence */
  425.     EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
  426.     if (error) {
  427.         printf("PLA comparison failed; the PLA's are not equivalent\n");
  428.         exit(1);
  429.     } else {
  430.         printf("PLA's compared equal\n");
  431.         exit(0);
  432.     }
  433.     break;    /* silly */
  434.  
  435.     case KEY_verify:            /* check two covers for equivalence */
  436.     Fold = PLA->F;    Dold = PLA->D;    F = PLA1->F;
  437.     EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
  438.     if (error) {
  439.         printf("PLA comparison failed; the PLA's are not equivalent\n");
  440.         exit(1);
  441.     } else {
  442.         printf("PLA's compared equal\n");
  443.         exit(0);
  444.     }    
  445.     break;    /* silly */
  446.  
  447.     case KEY_check:            /* check consistency */
  448.     (void) check_consistency(PLA);
  449.     print_solution = FALSE;
  450.     break;
  451.  
  452.     case KEY_mapdc:            /* compute don't care set */
  453.     map_dcset(PLA);
  454.     out_type = FD_type;
  455.     break;
  456.  
  457.     case KEY_equiv:
  458.     find_equiv_outputs(PLA);
  459.     print_solution = FALSE;
  460.     break;
  461.  
  462.     case KEY_separate:            /* remove PLA->D from PLA->F */
  463.     PLA->F = complement(cube2list(PLA->D, PLA->R));
  464.     break;
  465.  
  466.     case KEY_xor: {
  467.     pcover T1 = cv_intersect(PLA->F, PLA1->R);
  468.     pcover T2 = cv_intersect(PLA1->F, PLA->R);
  469.     free_cover(PLA->F);
  470.     PLA->F = sf_contain(sf_join(T1, T2));
  471.     free_cover(T1);
  472.     free_cover(T2);
  473.     break;
  474.     }
  475.  
  476.     case KEY_fsm: {
  477.     disassemble_fsm(PLA, summary);
  478.     print_solution = FALSE;
  479.     break;
  480.     }
  481.  
  482.     case KEY_test: {
  483.     pcover T, E;
  484.     T = sf_join(PLA->D, PLA->R);
  485.     E = new_cover(10);
  486.     sf_free(PLA->F);
  487.     EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
  488.     EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
  489.     EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
  490.     sf_free(T);
  491.     T = sf_join(PLA->F, PLA->R);
  492.     EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
  493.     EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
  494.     sf_free(T);
  495.     sf_free(E);
  496.     break;
  497.     }
  498.  
  499.  
  500.     }
  501.  
  502.     /* Print a runtime summary if trace mode enabled */
  503.     if (trace) {
  504.     runtime();
  505.     }
  506.  
  507.     /* Print total runtime */
  508.     if (summary || trace) {
  509.     print_trace(PLA->F, option_table[option].name, ptime()-start);
  510.     }
  511.  
  512.     /* Output the solution */
  513.     if (print_solution) {
  514.     EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
  515.     }
  516.  
  517.     /* Crash and burn if there was a verify error */
  518.     if (error) {
  519.     fatal("cover verification failed");
  520.     }
  521.  
  522.     /* cleanup all used memory */
  523.     free_PLA(PLA);
  524.     FREE(cube.part_size);
  525.     setdown_cube();             /* free the cube/cdata structure data */
  526.     sf_cleanup();               /* free unused set structures */
  527.     sm_cleanup();               /* sparse matrix cleanup */
  528.  
  529.     exit(0);
  530. }
  531.  
  532.  
  533. void getPLA(int opt, int argc, char *argv[], int option, pPLA *PLA, int out_type)
  534. {
  535.     FILE *fp;
  536.     int needs_dcset, needs_offset;
  537.     char *fname;
  538.  
  539.     if (opt >= argc) {
  540.     fp = stdin;
  541.     fname = "(stdin)";
  542.     } else {
  543.     fname = argv[opt];
  544.     if (strcmp(fname, "-") == 0) {
  545.         fp = stdin;
  546.     } else if ((fp = fopen(argv[opt], "r")) == NULL) {
  547.         fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
  548.         exit(1);
  549.     }
  550.     }
  551.     if (option_table[option].key == KEY_echo) {
  552.     needs_dcset = (out_type & D_type) != 0;
  553.     needs_offset = (out_type & R_type) != 0;
  554.     } else {
  555.     needs_dcset = option_table[option].needs_dcset;
  556.     needs_offset = option_table[option].needs_offset;
  557.     }
  558.  
  559.     if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
  560.     fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
  561.     exit(1);
  562.     }
  563.     (*PLA)->filename = util_strsav(fname);
  564.     filename = (*PLA)->filename;
  565. /*    (void) fclose(fp);*/
  566. /* hackto support -Dmany */
  567.     last_fp = fp;
  568. }
  569.  
  570.  
  571. void runtime(void)
  572. {
  573.     int i;
  574.     long total = 1, temp;
  575.  
  576.     for(i = 0; i < TIME_COUNT; i++) {
  577.     total += total_time[i];
  578.     }
  579.     for(i = 0; i < TIME_COUNT; i++) {
  580.     if (total_calls[i] != 0) {
  581.         temp = 100 * total_time[i];
  582.         printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
  583.         total_name[i], total_calls[i], print_time(total_time[i]),
  584.             temp/total, (10 * (temp%total)) / total);
  585.     }
  586.     }
  587. }
  588.  
  589.  
  590. void init_runtime(void)
  591. {
  592.     total_name[READ_TIME] =     "READ       ";
  593.     total_name[WRITE_TIME] =    "WRITE      ";
  594.     total_name[COMPL_TIME] =    "COMPL      ";
  595.     total_name[REDUCE_TIME] =   "REDUCE     ";
  596.     total_name[EXPAND_TIME] =   "EXPAND     ";
  597.     total_name[ESSEN_TIME] =    "ESSEN      ";
  598.     total_name[IRRED_TIME] =    "IRRED      ";
  599.     total_name[GREDUCE_TIME] =  "REDUCE_GASP";
  600.     total_name[GEXPAND_TIME] =  "EXPAND_GASP";
  601.     total_name[GIRRED_TIME] =   "IRRED_GASP ";
  602.     total_name[MV_REDUCE_TIME] ="MV_REDUCE  ";
  603.     total_name[RAISE_IN_TIME] = "RAISE_IN   ";
  604.     total_name[VERIFY_TIME] =   "VERIFY     ";
  605.     total_name[PRIMES_TIME] =   "PRIMES     ";
  606.     total_name[MINCOV_TIME] =   "MINCOV     ";
  607. }
  608.  
  609.  
  610. void subcommands(void)
  611. {
  612.     int i, col;
  613.     printf("                ");
  614.     col = 16;
  615.     for(i = 0; option_table[i].name != 0; i++) {
  616.     if ((col + strlen(option_table[i].name) + 1) > 76) {
  617.         printf(",\n                ");
  618.         col = 16;
  619.     } else if (i != 0) {
  620.         printf(", ");
  621.     }
  622.     printf("%s", option_table[i].name);
  623.     col += strlen(option_table[i].name) + 2;
  624.     }
  625.     printf("\n");
  626. }
  627.  
  628.  
  629. void usage(void)
  630. {
  631.     printf("%s\n\n", VERSION);
  632.     printf("SYNOPSIS: espresso [options] [file]\n\n");
  633.     printf("  -d        Enable debugging\n");
  634.     printf("  -e[opt]   Select espresso option:\n");
  635.     printf("                fast, ness, nirr, nunwrap, onset, pos, strong,\n");
  636.     printf("                eat, eatdots, kiss, random\n");
  637.     printf("  -o[type]  Select output format:\n");
  638.     printf("                f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
  639.     printf("  -rn-m     Select range for subcommands:\n");
  640.     printf("                d1merge: first and last variables (0 ... m-1)\n");
  641.     printf("                minterms: first and last variables (0 ... m-1)\n");
  642.     printf("                opoall: first and last outputs (0 ... m-1)\n");
  643.     printf("  -s        Provide short execution summary\n");
  644.     printf("  -t        Provide longer execution trace\n");
  645.     printf("  -x        Suppress printing of solution\n");
  646.     printf("  -v[type]  Verbose debugging detail (-v '' for all)\n");
  647.     printf("  -D[cmd]   Execute subcommand 'cmd':\n");
  648.     subcommands();
  649.     printf("  -Sn       Select strategy for subcommands:\n");
  650.     printf("                opo: bit2=exact bit1=repeated bit0=skip sparse\n");
  651.     printf("                opoall: 0=minimize, 1=exact\n");
  652.     printf("                pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
  653.     printf("                pairall: 0=minimize, 1=exact, 2=opo\n");
  654.     printf("                so_espresso: 0=minimize, 1=exact\n");
  655.     printf("                so_both: 0=minimize, 1=exact\n");
  656. }
  657.  
  658. /*
  659.  *  Hack for backward compatibility (ACK! )
  660.  */
  661.  
  662. void backward_compatibility_hack(int *argc, char **argv, int *option, int *out_type)
  663. {
  664.     int i, j;
  665.  
  666.     /* Scan the argument list for something to do (default is ESPRESSO) */
  667.     *option = 0;
  668.     for(i = 1; i < (*argc)-1; i++) {
  669.     if (strcmp(argv[i], "-do") == 0) {
  670.         for(j = 0; option_table[j].name != 0; j++)
  671.         if (strcmp(argv[i+1], option_table[j].name) == 0) {
  672.             *option = j;
  673.             delete_arg(argc, argv, i+1);
  674.             delete_arg(argc, argv, i);
  675.             break;
  676.         }
  677.         if (option_table[j].name == 0) {
  678.         fprintf(stderr,
  679.          "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
  680.         exit(1);
  681.         }
  682.         break;
  683.     }
  684.     }
  685.  
  686.     for(i = 1; i < (*argc)-1; i++) {
  687.     if (strcmp(argv[i], "-out") == 0) {
  688.         for(j = 0; pla_types[j].key != 0; j++)
  689.         if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
  690.             *out_type = pla_types[j].value;
  691.             delete_arg(argc, argv, i+1);
  692.             delete_arg(argc, argv, i);
  693.             break;
  694.         }
  695.         if (pla_types[j].key == 0) {
  696.         fprintf(stderr,
  697.            "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
  698.         exit(1);
  699.         }
  700.         break;
  701.     }
  702.     }
  703.  
  704.     for(i = 1; i < (*argc); i++) {
  705.     if (argv[i][0] == '-') {
  706.         for(j = 0; esp_opt_table[j].name != 0; j++) {
  707.         if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
  708.             delete_arg(argc, argv, i);
  709.             *(esp_opt_table[j].variable) = esp_opt_table[j].value;
  710.             break;
  711.         }
  712.         }
  713.     }
  714.     }
  715.  
  716.     if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
  717.     if (check_arg(argc, argv, "-fr")) input_type = FR_type;
  718.     if (check_arg(argc, argv, "-f")) input_type = F_type;
  719. }
  720.  
  721.  
  722. /* delete_arg -- delete an argument from the argument list */
  723. void delete_arg(int *argc, register char *argv[], int num)
  724. {
  725.     register int i;
  726.     (*argc)--;
  727.     for(i = num; i < *argc; i++) {
  728.     argv[i] = argv[i+1];
  729.     }
  730. }
  731.  
  732.  
  733. /* check_arg -- scan argv for an argument, and return TRUE if found */
  734. bool check_arg(int *argc, register char *argv[], register char *s)
  735. {
  736.     register int i;
  737.     for(i = 1; i < *argc; i++) {
  738.     if (strcmp(argv[i], s) == 0) {
  739.         delete_arg(argc, argv, i);
  740.         return TRUE;
  741.     }
  742.     }
  743.     return FALSE;
  744. }
  745.